﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SymbolIntegration.core.Expressions;
using Expression = SymbolIntegration.core.Expression;

namespace AnalyticIntegration.batch
{
    class Program
    {
        private const string c_CommentLine = "//";
        private const string c_EofSymbol = ".";
        private const string c_StdIn = "stdin";
        const string c_InputFileArg = "-input_file";
        static int Main(string[] args)
        {
            if (args.Count() < 2)
            {
                PrintUsage();
                return 1;
            }

            if (args[0] != c_InputFileArg)
            {
                PrintUsage();
                return 1;
            }

            List<string> text = args[1] == c_StdIn ? GetText(new ConsoleReadLine()) : GetText(new FileReadLine(args[1]));

            string sOutError;
            Expression result = null;
            try
            {
                result = ParseAndRunExpressionCommands(text, out sOutError);
            }
            catch (Exception ex)
            {
                sOutError = ex.Message + ". Detailed error:" + ex;
            }

            if (result == null)
            {
                PrintUsage("Failed to parse and run commands. Error: " + sOutError);
                return 3;
            }

            //FormatResult(result);

            string sResult = result.ToString();


            if (args.Count() < 3)
            {
                Console.WriteLine(sResult);
            }
            else
            {
                File.WriteAllText(args[2], sResult);
            }
            return 0;
        }

        //private static void FormatResult(AddendsExpression result)
        //{
        //    var newAddends = new ConstantExpression(0);
        //    var adddendsList = new List<KeyValuePair<Expression, Expression>>();


        //    foreach (var addend in result.Addends)
        //    {
        //        var dividedAddends = DivideByExp(addend);
        //        var firstEqualExp = adddendsList.FirstOrDefault(pair => pair.Key.IsEqual(dividedAddends.Key));
        //        if (firstEqualExp.Key == null)
        //        {
        //            adddendsList.Add(new KeyValuePair<Expression, Expression>(dividedAddends.Key, dividedAddends.Value));
        //        }
        //        else
        //        {
        //            firstEqualExp.Value = 
        //        }
        //    }
        //}

        private static KeyValuePair<Expression, Expression> DivideByExp(Expression addend)
        {
            throw new NotImplementedException();
        }

        private static Expression ParseAndRunExpressionCommands(List<String> text, out string sOutError)
        {
            Expression result = null;
            try
            {
                var thermalConductivityInterpretate = new ThermalConductivityInterpretate();

                result = thermalConductivityInterpretate.Run(text, out sOutError);

            }
            catch (Exception ex)
            {
                sOutError = ex.Message + ". " + ex;
            }

            return result;
        }

        private static List<String> GetText(ILineGetter lineGetter)
        {
            string sLine = lineGetter.ReadLine();
            var lines = new List<string>();
            while (true)
            {
                if (sLine == c_EofSymbol || sLine == null)
                {
                    break;
                }

                if (!sLine.TrimStart().StartsWith(c_CommentLine))
                {
                    lines.Add(sLine);
                }
                sLine = lineGetter.ReadLine();
            }

            return lines;
        }

        private static void PrintUsage(string additionalError = "")
        {
            string sText = additionalError == "" ? "" : "Error: " + additionalError + "\n";
            sText += "Usage:\n\t " + c_InputFileArg + " <input file>\n. Can be '" + c_StdIn +
                     "', if you want enter comands to stdin";
            Console.WriteLine(sText);
        }
    }
}
